/******************************************************************************
 * Copyright (C) 2011 ShenZhen ComTop Information Technology Co.,Ltd
 * All Rights Reserved.
 * 本软件为深圳康拓普开发研制。未经本公司正式书面同意，其他任何个人、团体不得使用、
 * 复制、修改或发布本软件.
 *****************************************************************************/

package com.code.common.sessioncache.action;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.code.common.utils.StringUtils;

/**
 * session包装过滤器
 * 
 * @author 郑重
 * @since 1.0
 * @version 2010-8-25 郑重
 */
public class SessionFilter extends HttpServlet implements Filter {
    
    /**
     * 会话ID名
     */
    private String sessionIdName;
    
    /**
     * cookie域
     */
    private String cookieDomain;
    
    /**
     * cookie路径
     */
    private String cookiePath;
    
    /**
     * 当前访问会话Id字典
     */
    private static final Map<String, String> SESSIONIDS_MAP = new HashMap<String, String>(1000);
    
    /**
     * 过滤器初始化
     * 
     * @param filterConfig FilterConfig
     * @throws ServletException ServletException
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化sessionId
        this.sessionIdName = filterConfig.getInitParameter("sessionId");
        if (this.sessionIdName == null) {
            this.sessionIdName = "cacheSessionName";
        }
        // 初始化cookieDomain
        this.cookieDomain = filterConfig.getInitParameter("cookieDomain");
        if (this.cookieDomain == null) {
            this.cookieDomain = StringUtils.EMPTY;
        }
        // 初始化cookiePath
        this.cookiePath = filterConfig.getInitParameter("cookiePath");
        if (StringUtils.isBlank(this.cookiePath)) {
            this.cookiePath = "/";
        }
    }
    
    /**
     * 执行过滤器
     * 
     * @param servletRequest ServletRequest
     * @param servletResponse ServletResponse
     * @param filterChain FilterChain
     * @throws IOException IOException
     * @throws ServletException ServletException
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse,
     *      javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String[] objSessionIds = getSessionId(request, response);
        filterChain.doFilter(new HttpServletRequestWrapper(objSessionIds[0], objSessionIds[1], request),
            servletResponse);
    }
    
    /**
     * 返回sessionId
     * 
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @return String[]
     */
    private String[] getSessionId(HttpServletRequest request, HttpServletResponse response) {
        String[] objSessionIds = new String[2];
        String strOldSession = StringUtils.EMPTY;
        Cookie objCookies[] = request.getCookies();
        if (objCookies != null && objCookies.length > 0) {
            for (int i = 0; i < objCookies.length; i++) {
                Cookie objCookie = objCookies[i];
                if (sessionIdName.equals(objCookie.getName())) {
                    strOldSession = objCookie.getValue();
                }
            }
        }
        
        HttpSession objSession = request.getSession(false);
        // 如果会话过期
        if (objSession == null && SESSIONIDS_MAP.get(strOldSession) != null && StringUtils.isNotBlank(strOldSession)) {
            objSessionIds[0] = strOldSession;
            objSessionIds[1] = strOldSession;
            // 移除全局会话标识
            SESSIONIDS_MAP.remove(strOldSession);
        } else if (objSession == null && SESSIONIDS_MAP.get(strOldSession) == null
            && StringUtils.isNotBlank(strOldSession)) {
            // 如果服务器宕机切换其他服务器
            objSessionIds[0] = strOldSession;
            // 写入全局会话字典
            SESSIONIDS_MAP.put(strOldSession, strOldSession);
        } else if (objSession != null) {
            // 正常请求
            objSessionIds[0] = strOldSession;
        }
        objSessionIds[0] = strOldSession;
        objSessionIds[1] = null;
        
        // 如果是第一次访问创建新回话Id
        if (StringUtils.isBlank(strOldSession)) {
            String strNewSession = java.util.UUID.randomUUID().toString();
            // 写入全局会话字典
            SESSIONIDS_MAP.put(strNewSession, strNewSession);
            objSessionIds[0] = strNewSession;
            Cookie objNewCookies = new Cookie(sessionIdName, strNewSession);
            objNewCookies.setMaxAge(-1);
            if (!StringUtils.EMPTY.equals(this.cookieDomain)) {
                objNewCookies.setDomain(this.cookieDomain);
            }
            objNewCookies.setPath(this.cookiePath);
            response.addCookie(objNewCookies);
        }
        return objSessionIds;
    }
}